package com.funtl.framework.java.util.common;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;

import com.funtl.framework.java.ssh.abstracts.AbstractEntity;
import com.funtl.framework.java.util.exception.UtilException;

/**
 * 通用反射工具
 * @author lwm
 *
 */
public class CommonReflex {
	/**
	 * 获取对象属性值
	 * @param obj 需要获取数据的对象
	 * @param propertyName 对象属性名称
	 * @return
	 * @throws UtilException
	 */
	public static Object getValue(Object obj, String propertyName) throws UtilException {
		try {
			return PropertyUtils.getSimpleProperty(obj, propertyName);
		} catch (IllegalAccessException e) {
			throw new UtilException("getValue", e);
		} catch (InvocationTargetException e) {
			throw new UtilException("getValue", e);
		} catch (NoSuchMethodException e) {
			throw new UtilException("getValue", e);
		}
	}
	
	/**
	 * 设置对象属性值
	 * @param obj
	 * @param propertyName
	 * @param propertyValue
	 */
	public static void setValue(Object obj, String propertyName, Object propertyValue) throws UtilException {
		try {
			PropertyUtils.setProperty(obj, propertyName, propertyValue);
		} catch (IllegalAccessException e) {
			throw new UtilException("setValue", e);
		} catch (InvocationTargetException e) {
			throw new UtilException("setValue", e);
		} catch (NoSuchMethodException e) {
			throw new UtilException("setValue", e);
		}
	}
	
	/**
	 * 获取对象非空属性的键值数据集合
	 * @param obj 需要获取数据的对象
	 * @return
	 * @throws UtilException
	 */
	public static void getKeyValue(Object obj, List<String> parentPropertyNames, Map<String, Object> result) throws UtilException {
		try {
			PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(obj.getClass());
			Object objVal = null;
			for (PropertyDescriptor pd : pds) {
				String pdName = pd.getName();
				objVal = PropertyUtils.getSimpleProperty(obj, pdName);
				if (objVal != null && !pdName.equals("class") && !pd.getPropertyType().getName().equals("java.util.List")) {
					if (objVal instanceof AbstractEntity)
					{//存在映射属性
						parentPropertyNames.add(pdName);
						getKeyValue(objVal, parentPropertyNames, result);
						continue;
					}
					if (parentPropertyNames == null || parentPropertyNames.size() == 0)
					{
						result.put(pdName, objVal);
					}
					else
					{
						StringBuilder nameBuilder = new StringBuilder();
						for (String n : parentPropertyNames)
						{
							nameBuilder.append(n);
							nameBuilder.append(".");
						}
						nameBuilder.append(pdName);
						result.put(nameBuilder.toString(), objVal);
					}
				}
			}
			if (parentPropertyNames != null && parentPropertyNames.size() > 0)
			{
				int length = parentPropertyNames.size();
				parentPropertyNames.remove(length - 1);
			}
		} catch (IllegalAccessException e) {
			throw new UtilException("getKeyValue", e);
		} catch (InvocationTargetException e) {
			throw new UtilException("getKeyValue", e);
		} catch (NoSuchMethodException e) {
			throw new UtilException("getKeyValue", e);
		}
	}
	
	/**
	 * 获取对象属性类型 <br />
	 * 类型格式如 <br />
	 * java.lang.Long <br />
	 * java.lang.Double <br />
	 * java.lang.Integer <br />
	 * java.util.Date
	 * @param obj 需要获取数据的对象
	 * @param propertyName 属性名称
	 * @return
	 */
	public static String getPropertyType(Object obj, String propertyName) throws UtilException {
		try {
			PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(obj, propertyName);
			return pd.getPropertyType().getName();
		} catch (IllegalAccessException e) {
			throw new UtilException("getPropertyType", e);
		} catch (InvocationTargetException e) {
			throw new UtilException("getPropertyType", e);
		} catch (NoSuchMethodException e) {
			throw new UtilException("getPropertyType", e);
		}
	}
	
	/**
	 * 获取对象属性数组
	 * @param obj 需要获取数据的对象
	 * @return
	 */
	public static String[] getPropertyTypes(Object obj) {
		PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(obj.getClass());
		String[] pts = new String[pds.length];
		for (int i = 0 ; i < pds.length ; i++) {
			pts[i] = pds[i].getName();
		}
		return pts;
	}
	
}
